Skip to content

gh-149306: Improve error messages in wave module to include the offending value#149307

Open
htjworld wants to merge 3 commits intopython:mainfrom
htjworld:gh-149306-wave-error-messages
Open

gh-149306: Improve error messages in wave module to include the offending value#149307
htjworld wants to merge 3 commits intopython:mainfrom
htjworld:gh-149306-wave-error-messages

Conversation

@htjworld
Copy link
Copy Markdown
Contributor

@htjworld htjworld commented May 3, 2026

Summary

Include the offending value in wave.Error messages raised by:

  • Wave_read._read_fmt_chunk (parses WAV file header)
  • Wave_write.setnchannels
  • Wave_write.setsampwidth
  • Wave_write.setframerate

Before:

wave.Error: bad # of channels
wave.Error: bad sample width
wave.Error: bad frame rate

After:

wave.Error: bad # of channels: 0
wave.Error: bad sample width: 0
wave.Error: bad frame rate: -1

Motivation

Wave_read: Values come from the WAV file header — they never appear
in the traceback. The error message is the only debugging clue.

Wave_write: When values originate from variables, configuration files,
or parsed data rather than literals, the traceback shows the call site but
not the value itself. For example, w.setframerate(config['rate']) raises
bad frame rate with no indication of what config['rate'] was.

This extends the clear-feedback approach introduced in gh-144976, which fixed
the validation order in setframerate to raise immediately at the point of
the mistake. Showing the offending value is the natural next step.

For setframerate, the original value (before int(round())) is shown rather
than the rounded result, so callers see exactly what they passed.

Precedent

Notes

  • Error type is unchanged; only the message text is refined.
  • The bits/bytes unit ambiguity in bad sample width predates this PR and can be addressed separately.
  • NaN/Inf handling in setframerate is pre-existing behaviour and out of scope here.

… offending value

Include the offending value in wave.Error messages raised by
Wave_read._read_fmt_chunk and Wave_write setters (setnchannels,
setsampwidth, setframerate). For setframerate, the original value is
shown rather than the rounded one to aid debugging.
@htjworld htjworld force-pushed the gh-149306-wave-error-messages branch 2 times, most recently from cc28830 to d1ba708 Compare May 3, 2026 02:14
Comment thread Lib/wave.py Outdated
def _read_fmt_chunk(self, chunk):
try:
self._format, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
self._format, nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't change this. It is a breaking change. Previously the attribute would have been already set after passing unpack_from but now it will be deferred.

Comment thread Lib/wave.py Outdated
Comment on lines +525 to +528
rounded = int(round(framerate))
if rounded <= 0:
raise Error(f'bad frame rate: {framerate!r}')
self._framerate = rounded
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rounded = int(round(framerate))
if rounded <= 0:
raise Error(f'bad frame rate: {framerate!r}')
self._framerate = rounded
rounded_framerate = int(round(framerate))
if rounded_framerate <= 0:
raise Error(f'bad frame rate: {framerate!r}')
self._framerate = rounded_framerate

Comment thread Lib/test/test_wave.py Outdated
Comment on lines +437 to +438
with self.assertRaisesRegex(wave.Error,
re.escape(f'bad # of channels: {nchannels!r}')):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability purposes, can you put the message outside?

message = re.escape(...)
with wave.open(...):
   with self.assertRaisesRegex(..., err):
        f.setchannels(channels)

@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 3, 2026

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@htjworld
Copy link
Copy Markdown
Contributor Author

htjworld commented May 3, 2026

I have made the requested changes; please review again

  • Reverted _read_fmt_chunk to assign directly to self._nchannels (no temporary variable)
  • Renamed rounded to rounded_framerate
  • Extracted assertRaisesRegex messages to variables for readability

@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 3, 2026

Thanks for making the requested changes!

@picnixz: please review the changes made to this pull request.

@bedevere-app bedevere-app Bot requested a review from picnixz May 3, 2026 12:02
@read-the-docs-community
Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #32514806 | 📁 Comparing 2d4c5e4 against main (836fbda)

  🔍 Preview build  

8 files changed · ± 8 modified

± Modified

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants